package timbap.visualizer.api.plugin.configuration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import timbap.visualizer.api.context.PluginContext;
import timbap.visualizer.api.plugin.Plugin;
import timbap.visualizer.api.plugin.configuration.binding.PluginBinding;
import timbap.visualizer.api.plugin.configuration.binding.PluginConfiguration;
import timbap.visualizer.api.plugin.container.RootPlugin;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;

/**
 * The <code>AbstractPluginManager</code> is the common
 * base implementation for all plugin managers.
 *
 * It parses the plugin configuration from an xml
 * configuration file and calls the unimplemented method
 * <code>loadPluginInstance(PluginBinding)</code>
 * for the root plugin. Afterwards it initializes
 * and activates it.
 *
 * @author  Andreas Pabst
 * @see     timbap.visualizer.api.plugin.Plugin
 * @see     timbap.visualizer.api.plugin.configuration.PluginManager
 */
public abstract class AbstractPluginManager implements PluginManager {

    private static final Log LOG = LogFactory.getLog(AbstractPluginManager.class);
    private static final String PLUGINS_BASE_PACKAGE = "timbap.visualizer.api.plugin.configuration.binding";
    private static final String DEFAULT_VISUALIZER_PLUGINS_CONFIG_FILE_PATH = "conf/visualizer_plugins.cfg.xml";

    protected RootPlugin rootPlugin;
    protected PluginConfiguration pluginConfig;

    protected abstract Plugin loadPluginInstance(PluginBinding pPluginBinding);

    public void readPluginConfiguration(PluginContext pPluginContext) {

        File pPluginConfigurationFile = new File(DEFAULT_VISUALIZER_PLUGINS_CONFIG_FILE_PATH);
        try{
            JAXBContext tJAXBContext = JAXBContext.newInstance(PLUGINS_BASE_PACKAGE);
            Unmarshaller tUnmarshaller = tJAXBContext.createUnmarshaller();
            pluginConfig = (PluginConfiguration)tUnmarshaller.unmarshal(pPluginConfigurationFile);
            LOG.info("Successfully parsed plugin configuration file " + pPluginConfigurationFile);
        } catch(Exception e){
            LOG.error("Error while parsing plugin configuration file " + pPluginConfigurationFile, e);
        }

        PluginBinding tRootPluginBinding = pluginConfig.getRootPlugin();
        Plugin tRootPlugin = loadPluginInstance(tRootPluginBinding);
        if (tRootPlugin instanceof RootPlugin) {
            rootPlugin = (RootPlugin)tRootPlugin;
            rootPlugin.init(pPluginContext);
            rootPlugin.activate();
        } else {
            LOG.error("Root Plugin " + tRootPlugin
                    + " of class " + tRootPlugin.getClass().getName()
                    + " does not implement " + RootPlugin.class.getSimpleName());
        }
    }

    public RootPlugin getRootPlugin() {
        return rootPlugin;
    }

}
